package org.jiuling.wechat.publicplatform.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jiuling.local.tools.exception.LocalToolsException;
import org.jiuling.local.tools.verify.*;
import org.jiuling.network.tools.http.request.HttpRequest;
import org.jiuling.network.tools.http.request.exception.RequestException;
import org.jiuling.network.tools.http.request.factory.HttpRequestFactory;
import org.jiuling.network.tools.http.request.model.HttpRequestBody;
import org.jiuling.network.tools.http.request.model.HttpRequestParam;
import org.jiuling.network.tools.http.request.model.HttpResponse;
import org.jiuling.wechat.publicplatform.api.enums.WeChatApiEnum;
import org.jiuling.wechat.publicplatform.exception.WeChatException;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

/**
 * 微信工具
 * @author 紫灵
 * @date 2022年04月20日 23时45分31秒
 */
public class WeChatUtil {

    /** 私有构造方法，禁止创建对象 */
    private WeChatUtil() {}

    /**
     * 验证是否成功并返回信息
     * @param httpResponse 请求响应
     * @throws WeChatException 微信异常信息
     */
    public static String verifySuccessAndReturnMsg(HttpResponse httpResponse) throws WeChatException {
        String body = httpResponse.getBody();
        JSONObject bodyJson = JSON.parseObject(body);
        Integer errcode = bodyJson.getInteger("errcode");
        if(!IntegerVerify.isNull(errcode) && bodyJson.getInteger("errcode") != 0){
            throw new WeChatException(bodyJson.getString("errmsg"));
        }
        return body;
    }

    /**
     * 解析Http响应
     * @param httpResponse Http响应
     * @return 泛型对象
     */
    public static <T> T analysisHttpResponse(HttpResponse httpResponse,String paramName,Class<T> clazz) throws WeChatException {
        String body = verifySuccessAndReturnMsg(httpResponse);
        JSONObject jsonBody = JSON.parseObject(body);
        // 当参数名称为空是不解析参数
        if(StringVerify.isBlank(paramName)){
            return jsonBody.toJavaObject(clazz);
        }else {
            Object bodyParam = jsonBody.get(paramName);
            if(bodyParam instanceof JSONObject){
               return (T) ((JSONObject) bodyParam).toJavaObject(clazz);
            }else if(bodyParam instanceof JSONArray){
               return (T) ((JSONArray) bodyParam).toJavaList(clazz);
            }else if(bodyParam instanceof Long){
                return (T) String.valueOf(bodyParam);
            }else {
                throw new WeChatException("未能识别的body类型！");
            }
        }
    }

    /**
     * 请求
     * @param weChatApiEnum 微信api枚举
     * @param httpRequestParam 请求参数
     * @param httpRequestBody 请求头
     * @return 泛型对象
     * @param <T> 泛型对象
     * @throws WeChatException 微信异常信息
     */
    public static  <T> T request(WeChatApiEnum weChatApiEnum, HttpRequestParam httpRequestParam, HttpRequestBody httpRequestBody) throws WeChatException {
        // 创建Http请求对象
        HttpRequest httpRequest = new HttpRequest();
        String name = weChatApiEnum.getName();
        try {
            HttpRequestFactory httpRequestFactory = httpRequest.openHttpRequestFactory(weChatApiEnum.getUrl())
                    // 设置请求方式
                    .setRequestMethod(weChatApiEnum.getRequestMethod());
            String[] bodyName = weChatApiEnum.getBodyName();
            if(!ArrayVerify.isNull(bodyName)) {
                verifyApiData(name,"请求内容",bodyName,httpRequestBody);
                // 设置请求内内容
                httpRequestFactory.setRequestBody(httpRequestBody);
            }
            String[] paramName = weChatApiEnum.getParamName();
            if(!ArrayVerify.isNull(paramName)) {
                verifyApiData(name,"请求参数",paramName,httpRequestParam);
                // 设置请求参数
                httpRequestFactory.setRequestParam(httpRequestParam);
            }
            HttpResponse httpResponse = httpRequest.send();
            // TODO 后续可以考虑加入DEBUG日志
            Class<?> clazz = weChatApiEnum.getClazz();
            // 判断返回对象是否为空，如果为空则返回是否请求成功
            if(ObjectVerify.isNull(clazz)){
                WeChatUtil.verifySuccessAndReturnMsg(httpResponse);
                return (T) Boolean.valueOf(true);
            }else {
                return (T) WeChatUtil.analysisHttpResponse(httpResponse, weChatApiEnum.getAnalysisParamName(), weChatApiEnum.getClazz());
            }
        } catch (RequestException | IOException | LocalToolsException | NoSuchAlgorithmException |
                 KeyManagementException | WeChatException e) {
            throw new WeChatException(e.getLocalizedMessage());
        }
    }

    /**
     * 校验接口数据
     * @param name 接口名称
     * @param type 数据类型
     * @param dataNames 数据名称数组
     * @param datas 数据
     * @throws WeChatException 微信异常
     */
    private static void verifyApiData(String name, String type, String[] dataNames, Map<String,Object> datas) throws WeChatException {
        for(String dataName : dataNames){
            if(MapVerify.isNull(datas)){
                throw new WeChatException(name+"接口，"+type+"数据不存在！");
            }
            if(!datas.containsKey(dataName)){
                throw new WeChatException(name+"接口，"+type+"数据"+dataName+"缺失！");
            }
        }
    }
}
